package com.example.demo.serial_test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ObjectToByteArray {

    // 将对象数组转换为字节数组
    public static byte[] objectArrayToByteArray(Serializable[] objects) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {

            oos.writeObject(objects);
            return baos.toByteArray();
        }
    }

    // 从字节数组恢复对象数组
    public static Object[] byteArrayToObjectArray(byte[] bytes)
            throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
             ObjectInputStream ois = new ObjectInputStream(bais)) {

            return (Object[]) ois.readObject();
        }
    }

    /**
     * 方法1: 使用Java序列化（最简单，但要求所有对象可序列化）
     */
    public static byte[] convertUsingSerialization(Object[] objects) throws IOException {
        if (objects == null) {
            return new byte[0];
        }

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {

            oos.writeObject(objects);
            oos.flush();
            return baos.toByteArray();
        }
    }

    /**
     * 方法2: 智能转换 - 根据对象类型选择最佳方式
     */
    public static byte[] convertSmart(Object[] objects) throws IOException {
        if (objects == null || objects.length == 0) {
            return new byte[0];
        }

        // 检查数组中的对象类型
        Class<?> firstClass = objects[0].getClass();

        // 如果是基本类型包装类或String，使用优化方式
        if (firstClass == String.class) {
            return convertStringArray((String[]) objects);
        } else if (firstClass == Integer.class) {
            return convertIntegerArray((Integer[]) objects);
        } else if (firstClass == Long.class) {
            return convertLongArray((Long[]) objects);
        } else if (firstClass == Double.class) {
            return convertDoubleArray((Double[]) objects);
        } else if (firstClass == Float.class) {
            return convertFloatArray((Float[]) objects);
        } else if (firstClass == Boolean.class) {
            return convertBooleanArray((Boolean[]) objects);
        } else {
            // 其他对象类型使用序列化
            return convertUsingSerialization(objects);
        }
    }

    /**
     * 方法3: 手动处理String数组（优化性能）
     */
    private static byte[] convertStringArray(String[] strings) {
        List<byte[]> byteList = new ArrayList<>();
        int totalLength = 0;

        for (String str : strings) {
            byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
            byteList.add(strBytes);
            totalLength += 4 + strBytes.length; // 4字节存储长度
        }

        ByteBuffer buffer = ByteBuffer.allocate(totalLength);
        for (byte[] strBytes : byteList) {
            buffer.putInt(strBytes.length); // 写入字符串长度
            buffer.put(strBytes);           // 写入字符串内容
        }

        return buffer.array();
    }

    /**
     * 方法4: 手动处理Integer数组
     */
    private static byte[] convertIntegerArray(Integer[] integers) {
        ByteBuffer buffer = ByteBuffer.allocate(integers.length * 4);
        for (Integer num : integers) {
            buffer.putInt(num);
        }
        return buffer.array();
    }

    /**
     * 方法5: 手动处理Long数组
     */
    private static byte[] convertLongArray(Long[] longs) {
        ByteBuffer buffer = ByteBuffer.allocate(longs.length * 8);
        for (Long num : longs) {
            buffer.putLong(num);
        }
        return buffer.array();
    }

    /**
     * 方法6: 手动处理Double数组
     */
    private static byte[] convertDoubleArray(Double[] doubles) {
        ByteBuffer buffer = ByteBuffer.allocate(doubles.length * 8);
        for (Double num : doubles) {
            buffer.putDouble(num);
        }
        return buffer.array();
    }

    /**
     * 方法7: 手动处理Float数组
     */
    private static byte[] convertFloatArray(Float[] floats) {
        ByteBuffer buffer = ByteBuffer.allocate(floats.length * 4);
        for (Float num : floats) {
            buffer.putFloat(num);
        }
        return buffer.array();
    }

    /**
     * 方法8: 手动处理Boolean数组
     */
    private static byte[] convertBooleanArray(Boolean[] booleans) {
        ByteBuffer buffer = ByteBuffer.allocate(booleans.length);
        for (Boolean bool : booleans) {
            buffer.put((byte) (bool ? 1 : 0));
        }
        return buffer.array();
    }

    /**
     * 从字节数组恢复对象数组（通用方法）
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
        if (bytes == null || bytes.length == 0) {
            return (T[]) new Object[0];
        }

        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
             ObjectInputStream ois = new ObjectInputStream(bais)) {

            return (T[]) ois.readObject();
        }
    }

    // 示例使用
    public static void main(String[] args) {
        try {
            List<String> list = Arrays.asList("1", "2");
            Object[] array = list.toArray();
            byte[] bytes = convertSmart(array);
            String hexStrAll =convertByteArrayToHexStr(bytes);
            System.out.println(hexStrAll);

            int len, pos = 0;
            String tag = "";
            String lenHexStr = "";
            String valHexStr = "";
            tag = hexStrAll.substring(pos, pos + 4);
            pos = pos + 4;
            lenHexStr = hexStrAll.substring(pos, pos + 4);
            pos = pos + 4;
            len = Integer.parseInt(lenHexStr, 16) * 2;
            valHexStr = hexStrAll.substring(pos, pos + len);
            pos = pos + len;
            System.out.println(tag);
            System.out.println(len);
            System.out.println(lenHexStr);
            System.out.println(valHexStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将字节数组转换成十六进制字符串
     *
     * @param srcByteArray 字节数组
     * @return 十六进制字符串
     */
    public static String convertByteArrayToHexStr(byte[] srcByteArray) {
        String sTemp = null;
        StringBuffer sOutLine = new StringBuffer();
        byte[] inByte = srcByteArray;
        for (int iSerie = 0; iSerie < inByte.length; iSerie++) {
            // System.out.println("inbyte"+iSerie+inByte[iSerie]);
            if (inByte[iSerie] < 0) {
                sTemp = Integer.toHexString(256 + inByte[iSerie]);
            } else {
                sTemp = Integer.toHexString(inByte[iSerie]);
            }
            if (sTemp.length() < 2) {
                sTemp = "0" + sTemp;
            }
            sTemp = sTemp.toUpperCase();
            sOutLine = sOutLine.append(sTemp);
        }
        return sOutLine.toString();
    }
}